<script setup>
import {ref, onMounted, onUnmounted, defineProps, nextTick, defineComponent, watch} from 'vue'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

import { RoundedBoxGeometry } from 'three/examples/jsm/geometries/RoundedBoxGeometry.js';
import {gridConfig} from '/src/config/grid.config.js';
import {shelfTypes} from '/src/config/shelfTypes.config.js';
import shelvesapi from '/src/config/shelves.api.json';
const props = defineProps({
  warehouseSize: {
    type: Object,
    default: () => ({ length: 90, width: 90 })
  },

  shelves: {
    type: Array,
    default: () => []//shelves
  }
})

const container = ref(null)
const warehouseContainer = ref(null);
let scene, camera, renderer, controls

function createshelves() {
  // 创建货架
  props.shelves.forEach((shelfConfig, index) => {
    const col = index % gridConfig.columns;
    const row = Math.floor(index / gridConfig.columns);

    const position = {
      x: (col - gridConfig.columns / 2) * gridConfig.cellWidth,
      y: (row - gridConfig.rows / 2) * gridConfig.cellHeight,
      z: shelfConfig.position.z
    };

    const geometry = new THREE.BoxGeometry(
        shelfConfig.size.width,
        shelfConfig.size.height,
        shelfConfig.size.depth
    );
    const material = new THREE.MeshPhongMaterial({
      color: new THREE.Color(shelfConfig.color),
      wireframe: false
    })
    const shelf = new THREE.Mesh(geometry, material)
    shelf.userData.isShelf = true
    shelf.userData.index = props.shelves.indexOf(shelfConfig)
    shelf.position.set(
        shelfConfig.position.x,
        shelfConfig.position.z,
        shelfConfig.position.y
    )
    scene.add(shelf)
  })
}
function initScene() {
  scene = new THREE.Scene()
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
  const containerWidth = container.value.clientWidth || 1250; // 默认值
  const containerHeight = container.value.clientHeight || 600;
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(containerWidth, containerHeight)
  renderer.setPixelRatio(window.devicePixelRatio)
  container.value.appendChild(renderer.domElement)

  // 创建地面网格
  const gridSize = Math.max(gridConfig.columns * gridConfig.cellWidth, gridConfig.rows * gridConfig.cellHeight);
  const gridHelper = new THREE.GridHelper(gridSize, gridConfig.columns);

  scene.add(gridHelper)

  // 创建小球
  // 创建圆角长方体
  const ballGeometry = new RoundedBoxGeometry(4, 2, 4, 0.5, 1);
  const ballMaterial = new THREE.MeshPhongMaterial({ color: 0xff7700 });
  ball = new THREE.Mesh(ballGeometry, ballMaterial);
  ball.position.set(-22, 2, 42); // 调整初始高度
  scene.add(ball);

  // 创建仓库地面
  const groundGeometry = new THREE.PlaneGeometry(
      gridConfig.columns * gridConfig.cellWidth,
      gridConfig.rows * gridConfig.cellHeight
  )
  const groundMaterial = new THREE.MeshPhongMaterial({ color: 0x888888, side: THREE.DoubleSide })
  const ground = new THREE.Mesh(groundGeometry, groundMaterial)
  ground.rotation.x = Math.PI / 2
  scene.add(ground)

  // 创建带箭头虚线路径
  const lineGeometry = new THREE.BufferGeometry().setFromPoints([
    new THREE.Vector3(22, 1, 45),
    new THREE.Vector3(22, 1, 2)
  ]);

  const lineMaterial = new THREE.LineDashedMaterial({
    color: 0x00ff00,
    dashSize: 1,
    gapSize: 0.5,
    linewidth: 2
  });
  const dashedLine = new THREE.Line(lineGeometry, lineMaterial);
  dashedLine.computeLineDistances();
  scene.add(dashedLine);

  // 创建带箭头虚线路径
  const lineGeometry2 = new THREE.BufferGeometry().setFromPoints([

    new THREE.Vector3(22, 1, 2),
    new THREE.Vector3(26, 1, 2)
  ]);

  const lineMaterial2 = new THREE.LineDashedMaterial({
    color: 0x00ff00,
    dashSize: 1,
    gapSize: 0.5,
    linewidth: 2
  });
  const dashedLine2 = new THREE.Line(lineGeometry2, lineMaterial2);
  dashedLine2.computeLineDistances();
  scene.add(dashedLine2);



  // createshelves();
  // 添加环境光
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5)
  scene.add(ambientLight)

  // 添加平行光
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
  directionalLight.position.set(20, 30, 20)
  scene.add(directionalLight)

  camera.position.set(0, 50, 70)
  camera.lookAt(0, 0, 0)

  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
  controls.dampingFactor = 0.05
}
let isScaling = false;
let targetScale = 1;

const ballSpeed = 0.1;
let ball = null;
let ballMoving = true;
//移动方向
let dic = 0;
function animate() {
  requestAnimationFrame(animate)
  controls.update()

  if (ballMoving) {
    if (dic == 0) {
      if (ball.position.z <= 2) {
        dic = 1;

      }
      ball.position.z -= ballSpeed;
    }
    else if (dic == 1) {
      if (ball.position.x <= -22 - 3) {

        //isScaling = true;
        targetScale = 0.1;

        ball.scale.set(0.1, 1, 1);
        setTimeout(() => {
          ball.scale.set(1, 1, 1);
        }, 500);
        dic = 2;
        //isScaling = false;
      }
      ball.position.x -= ballSpeed;

    }
    else if (dic == 2) {
      if (ball.position.x >= -22) {
        dic = 3;
      }
      ball.position.x += ballSpeed;
    }
    else if (dic == 3) {
      if (ball.position.z >= 43) {
        dic = 0
      }
      ball.position.z += ballSpeed;
    }

  }

  if (isScaling) {
    //scaleFactor = THREE.MathUtils.lerp(scaleFactor, targetScale, 0.1);
    ball.scale.set(targetScale, 1, 1);
    // if (Math.abs(scaleFactor - targetScale) < 0.01) {
    //   isScaling = false;
    // }
  }

  renderer.render(scene, camera)
}


function onWindowResize() {
  camera.aspect = container.value.clientWidth / container.value.clientHeight
  camera.updateProjectionMatrix()
  renderer.setSize(container.value.clientWidth, container.value.clientHeight)
}

// 新增拖拽相关状态
const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()
let selectedShelf = null
let offset = new THREE.Vector3()

// 新增事件处理函数
function handleMouseDown(event) {
  const rect = renderer.domElement.getBoundingClientRect()
  mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
  mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1

  if (movecamera) {
    // 转换鼠标坐标为标准化设备坐标
    const mouseNDC = new THREE.Vector2(
        (mouse.x / window.innerWidth) * 2 - 1,
        -(mouse.y / window.innerHeight) * 2 + 1
    );

    // 创建射线投射器
    const raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(mouseNDC, camera);

    // 计算与地面平面的交点
    const groundNormal = new THREE.Vector3(0, 1, 0);
    const groundPoint = new THREE.Vector3(0, 0, 0);
    const plane = new THREE.Plane().setFromNormalAndCoplanarPoint(groundNormal, groundPoint);
    const targetPosition = new THREE.Vector3();
    raycaster.ray.intersectPlane(plane, targetPosition);

    // 限制移动范围
    const BOUNDARY = 40;
    targetPosition.x = THREE.MathUtils.clamp(targetPosition.x, -BOUNDARY, BOUNDARY);
    targetPosition.z = THREE.MathUtils.clamp(targetPosition.z, -BOUNDARY, BOUNDARY);

    // 平滑移动
    camera.position.lerp(targetPosition.setY(50), 0.1);
    controls.target.lerp(targetPosition.setY(0), 0.1);
    controls.update();
  }
  raycaster.setFromCamera(mouse, camera)
  const intersects = raycaster.intersectObjects(scene.children, true)

  if (intersects.length > 0) {
    const intersect = intersects.find(i => i.object.userData.isShelf)
    if (intersect) {
      selectedShelf = intersect.object
      controls.enabled = false

      // 计算点击位置与物体中心的偏移量
      const worldPosition = new THREE.Vector3()
      selectedShelf.getWorldPosition(worldPosition)
      offset.copy(worldPosition).sub(intersect.point)
    }
  }
}
//控制物体不偏移 新坐标-原始坐标必须为网格的整数倍
function _formatx(svalue, value) {
  if (!svalue)
    svalue = 0;
  else
    svalue = Math.round(svalue)
  let newlocation = Math.round(value / 3) * 3;

  svalue % 3 != 0 ? newlocation += 1.5 : newlocation;

  return newlocation;
}
function handleMouseMove(event) {
  if (!selectedShelf) return

  const rect = renderer.domElement.getBoundingClientRect()
  mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
  mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1
  // console.log(mouse.x)
  // mouse.x = _formatx(mouse.x)
  // console.log(mouse.x)
  // 计算新的三维位置（仅在XZ平面移动）
  raycaster.setFromCamera(mouse, camera)
  const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)
  const intersection = new THREE.Vector3()
  raycaster.ray.intersectPlane(plane, intersection)

  if (intersection) {
    selectedShelf.position.set(
        _formatx(selectedShelf.position.x, intersection.x + offset.x),
        selectedShelf.position.y,
        _formatx(selectedShelf.position.z, intersection.z + offset.z)
    );

    // 更新props中的货架位置
    const shelfIndex = selectedShelf.userData.index
    props.shelves[shelfIndex].position.x = _formatx(props.shelves[shelfIndex].position.x, intersection.x + offset.x);
    props.shelves[shelfIndex].position.z = _formatx(props.shelves[shelfIndex].position.z, intersection.z + offset.z);
  }
}

function handleMouseUp() {
  selectedShelf = null
  controls.enabled = true
}
/**
 * 通过物品类型和位置得到地图中的坐标
 * @param {*} position
 */
function ProcessPosition(shelfitem) {
  let shelftype = shelfTypes[item.code];
  let newlocation = Math.round(position / 3) * 3;
}
onMounted(() => {
  initScene();
  if (props.shelves && props.shelves.length > 0) {
    createshelves();
  }


  // myshf.forEach(item => {
  //   if (item && item.type && item.position && shelfTypes[item.type]) {
  //     console.log(JSON.stringify(item))
  //     createObject({
  //       type: item.type,
  //       position: item.position
  //     });
  //   }
  // })
  animate()
  window.addEventListener('resize', onWindowResize)

  // 添加事件监听
  nextTick(() => {
    if (renderer.domElement) {
      renderer.domElement.addEventListener('mousedown', handleMouseDown)
      renderer.domElement.addEventListener('mousemove', handleMouseMove)
      renderer.domElement.addEventListener('mouseup', handleMouseUp)
    }
  })
})

onUnmounted(() => {
  window.removeEventListener('resize', onWindowResize)
  container.value.removeChild(renderer.domElement)
  scene.dispose()
})
let ballbuttonshow = ref('暂停小车运动');
function movecontrol() {
  ballMoving = !ballMoving
  ballbuttonshow.value = ballMoving ? '暂停小车运动' : '开始小车运动';
}
let movecamera = false;
//随机切换视角

let camebuttonshow = ref('关闭视角跟随');
function changecamera() {
  movecamera = !movecamera;
  camebuttonshow.value = movecamera ? '开启视角跟随' : '关闭视角跟随';
}

// 新增拖拽处理函数
function handleDragStart(event, type) {
  event.dataTransfer.setData('application/json', JSON.stringify({ type }));
}

function handleDrop(event) {
  const data = JSON.parse(event.dataTransfer.getData('application/json'));
  const rect = renderer.domElement.getBoundingClientRect();
  const mouse = new THREE.Vector2(
      ((event.clientX - rect.left) / rect.width) * 2 - 1,
      -((event.clientY - rect.top) / rect.height) * 2 + 1
  );

  raycaster.setFromCamera(mouse, camera);
  const intersects = raycaster.intersectObjects(scene.children);

  if (intersects.length > 0) {
    const pos = intersects[0].point;
    createObject({
      type: data.type,
      position: {
        x: _formatx(1.5, pos.x),
        y: _formatx(1.5, pos.z),
        z: 1.4
      }
    });
  }
}

function createObject(config) {
  const geometry = config.type === 'charger'
      ? new RoundedBoxGeometry(2, 2, 2,)
      : new THREE.BoxGeometry(2.8, 2.8, 2.8);

  const material = new THREE.MeshPhongMaterial({
    color: config.type === 'charger' ? 0xFFA500 : 0x000000
  });

  const newShelf = {
    size: config.type === 'charger' ? { width: 4, height: 4, depth: 4 } : { width: 2.8, height: 2.8, depth: 2.8 },
    position: config.position,
    color: config.type === 'charger' ? 'orange' : 'black'
  };
  props.shelves.push(newShelf);

  const mesh = new THREE.Mesh(geometry, material);
  mesh.userData.isShelf = true;
  mesh.userData.index = props.shelves.length - 1;
  mesh.position.set(config.position.x, config.position.z, config.position.y);
  scene.add(mesh);
  let mysize = config.type === 'charger' ? { width: 2, height: 2, depth: 2 } : { width: 2.8, height: 2.8, depth: 2.8 };
  props.shelves.push({
    size: config.type === 'charger' ? { width: 2, height: 2, depth: 2 } : { width: 2.8, height: 2.8, depth: 2.8 },
    position: config.position,
    color: config.type === 'charger' ? 'orange' : 'black'
  });
}
let isPanelExpanded=ref(true);
defineOptions({
  name: 'WarehouseViewer'
});
defineExpose({
  initScene,
  animate
});
watch(() => props.shelves, () => {
  // 清除旧场景并重新初始化
  scene.clear();
  createshelves();
  initScene();
}, { deep: true });
</script>

<template>
  <div class="container" ref="container">
    <div class="controlpannel" :class="{ collapsed: !isPanelExpanded }">
      <button class="toggle-btn" @click="isPanelExpanded = !isPanelExpanded" >
        {{ isPanelExpanded ? '◀' : '▶' }}
      </button>
      <div v-show="isPanelExpanded">
        <!-- 原有控制面板内容 -->
        <div style="width: 100%;border: 1px solid;">
          <button @click="movecontrol">
            {{ ballbuttonshow }}
          </button>
        </div>
        <div style="width: 100%;border: 1px solid;">
          <button @click="changecamera">
            {{ camebuttonshow }}
          </button>
        </div>
        <div style="height: 50px;">
          <table style="width: 100%;">
            <tr>
              <td style="width: 30%;height: 50px;"> <label>充电桩:</label> </td>
              <button style="background-color: orange;width: 90%;border: 0px;" draggable="true"
                      @dragstart="handleDragStart($event, 'charger')"></button>
            </tr>
          </table>
          <table style="width: 100%;">
            <tr>
              <td style="width: 30%;height: 50px;"> <label>格口:</label> </td>
              <button style="background-color: black;width: 90%;border: 0px;" draggable="true"
                      @dragstart="handleDragStart($event, 'grid')"></button>
            </tr>
          </table>
        </div>
      </div>
    </div>
    <div ref="warehouseContainer" class="warehouse-container" :style="{ left: isPanelExpanded ? '200px' : '60px' }" />
  </div>
</template>

<style scoped>
.container {
  display: flex;
  width: 100%;
  height: 100vh;
  position: relative;
}

.controlpannel {
  flex: 0 0 15%; /* 固定 20% 宽度 */
  transition: width 0.3s ease;
  position: relative;
  height: 100%;
  overflow: hidden;
  z-index: 1000;
}

.controlpannel.collapsed {
  flex: 0 0 60px; /* 折叠时宽度 */
}



.toggle-btn {
  position: relative;
  z-index: 100;
  padding: 5px 10px;
  background: #f0f0f0;
  border: 1px solid #ccc;
  cursor: pointer;
}

</style>
